﻿using Chemistry.Models;
using Chemistry.WorkFlow;
using GalaSoft.MvvmLight.Command;
using OPCAutomation;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO.Ports;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Chemistry.Tools;

namespace Chemistry.ViewModels
{
    public class EquipmentViewModel:VmBase
    {
        #region 字段 
        private Examinee _currentExaminee;
        private WorkFlowBase _currentFlow;
        private ConfigModel _config ;
        private List<ExaminationPoint> _points;
        private SerialPort _port;
        private OPCServer _opcServer;
        private ExamInfo _selectedExamInfo;
        private bool _isStep;//是否分步骤考试
        private List<ButtonInformation> _buttonInformations;
        private bool _isExaming;
        private bool _isInputed;
        #endregion

        #region 通知 属性

        private ObservableCollection<ExamInfo> _examinfoes;
        public ObservableCollection<ExamInfo> ExamInfoes
        {
            get { return _examinfoes; }
            set { _examinfoes = value; RaisePropertyChanged("ExamInfoes"); }
        }

       

        private bool _isopcconnected;

        public bool IsOPCConnected
        {
            get { return _isopcconnected; }
            set { _isopcconnected = value; RaisePropertyChanged("IsOPCConnected"); }
        }

        private bool _isserialportconnected;

        public bool IsSerialPortConnected
        {
            get { return _isserialportconnected; }
            set { _isserialportconnected = value; RaisePropertyChanged("IsSerialPortConnected"); }
        }


        private bool _isinner;

        public bool IsInner
        {
            get { return _isinner; }
            set { _isinner = value; RaisePropertyChanged("IsInner"); }
        }

        #endregion

        #region 命令
        public RelayCommand LinkCommand { get; set; }
        public RelayCommand CheckStateCommand { get; set; }
        public RelayCommand InputCommand { get; set; }
        public RelayCommand SelectQuestionCommand { get; set; }
        public RelayCommand BeginCommand { get; set; }

        public RelayCommand CheckSelectedCommand { get; set; }  
        #endregion

        public EquipmentViewModel()
        {
            InputCommand = new RelayCommand(InputExec, CanInput);
            LinkCommand = new RelayCommand(LinkExec, () => _selectedExamInfo != null && _selectedExamInfo.Permission.CanLink && !_isExaming);
            CheckStateCommand = new RelayCommand(CheckStateExec, () => _selectedExamInfo != null && _selectedExamInfo.Permission.CanCheckState);
            SelectQuestionCommand = new RelayCommand(SelectQuestionExec,
                () => _selectedExamInfo != null && _selectedExamInfo.Permission.CanSelectQuestion);
            BeginCommand = new RelayCommand(BeginExec, () => _selectedExamInfo!=null && _selectedExamInfo.Permission.CanBeginExam);
            CheckSelectedCommand = new RelayCommand(
                CheckSelectedExec,
                () => _selectedExamInfo != null && _selectedExamInfo.Permission.CanCheckSelected);
            InitMessage();
            
        }

        private bool CanInput()
        {
            var b = _selectedExamInfo != null && _selectedExamInfo.Permission.CanInput && !_isInputed;
            return b;
        }

        private void InitMessage()
        {
            Register(this, MessageToken.ShowExamWindow, (i) =>
            {
                _config = Tools.Tool.GetConfig();
                IsInner = _config.IsInner;
                InitExamInfoes();
            });

            //确认完毕准考证之后 开始考试
            Register<Examinee>(this, MessageToken.BeginExaming, async (i) =>
            {
                _isInputed = true;//输入完准考证
                _currentExaminee = i;
                var ispass = await BeginExaming();
                if (ispass)
                {
                    ExamInfoMessage msg = new ExamInfoMessage()
                    {
                        ExamInfo = _selectedExamInfo,
                        IsFirstShow = true,
                        ButtonInformations = _buttonInformations,
                         IsStep = this._isStep,
                        Points = _points
                    };
                    //开始考试，弹出考试状态窗口
                    Send<ExamInfoMessage>(msg, MessageToken.ShowExamingWindow);
                }
            });

            Register<List<ExaminationPoint>>(this, MessageToken.ShowInputNumber, (i) =>
            {
                _isStep = true;
                _points = i;
                _selectedExamInfo.Permission.CanCheckSelected = true;
            });

            Register<object>(this,MessageToken.StopExaming,
                (i) =>
                    {
                        _currentFlow.Close();
                    });
            Register<bool>(this, MessageToken.IsExaming, (i) =>
            {
                _isInputed = i;
                _isExaming = i;
            });
        }

        private async Task<bool> BeginExaming()
        {
            if (_port != null && !_port.IsOpen)
            {
                _port.Open();
            }
            Send<string>("加载题目中......", MessageToken.ShowExamLoadMessage);
            await Task.Delay(500);
            bool ispass = false;
            _selectedExamInfo.TicketId = _currentExaminee.TicketId;
            _selectedExamInfo.LoginDate = DateTime.Now;
            _selectedExamInfo.Examinee = _currentExaminee;
            _selectedExamInfo.Name = _currentExaminee.Name;
            _selectedExamInfo.Score = 0;

            _currentFlow = GetFlow();

            _selectedExamInfo.WorkFlow = _currentFlow;
            string msg = await _currentFlow.CheckDefault();
            if (string.IsNullOrEmpty(msg))
            {
                _currentFlow.Begin();
                ispass = true;
                _selectedExamInfo.ExamState = ExamState.考试中;
                _selectedExamInfo.Permission.CanCommit = true;
                _selectedExamInfo.Permission.CanCheckState = true;
                _selectedExamInfo.Permission.CanPrint = false;
                _selectedExamInfo.Permission.CanInput = false;
                _selectedExamInfo.Permission.CanBeginExam = false;
                _selectedExamInfo.Permission.CanSelectQuestion = false;
                
                Send<string>("加载题目中......", MessageToken.CloseExamLoadMessage);
            }
            else
            {
                Send<string>("加载题目中......", MessageToken.CloseExamLoadMessage);
                await Task.Delay(500);
                Send<string>(msg, MessageToken.ShowExamMessage);
                _selectedExamInfo.Permission.CanBeginExam = true;
            }
            return ispass;
        }

       private WorkFlowBase GetFlow()
        {
            Assembly assembly = Assembly.GetExecutingAssembly();
            List<object> parameters = new List<object>();
            parameters.Add(_opcServer);
            parameters.Add(_port);
            parameters.Add(_config != null && Tool.GetConfig().IsInner);
            string suffix = string.Empty;
            if (_isStep)
            {
                suffix = "_Step";
                parameters.Add(_points);
            }
            string classfullname = string.Format("Chemistry.WorkFlow.{0}{1}", Global.CurrentWorkflowName, suffix);
            object o = assembly.CreateInstance(classfullname, true, BindingFlags.Default, null, parameters.ToArray(), null, null);
            return o as WorkFlowBase;
        }

        #region 命令方法
        /// <summary>
        /// 查看选择的题目
        /// </summary>
        private void CheckSelectedExec()
        {
            Send<List<ExaminationPoint>>(_points, MessageToken.CheckSelectedQuestion);
        }

        private async void BeginExec()
        {
            if (_port != null && !_port.IsOpen)
            {
                _port.Open();
            }
            Send<string>("加载题目中......", MessageToken.ShowExamLoadMessage);
            bool ispass = false;
            await Task.Delay(500);
            string msg = await _currentFlow.CheckDefault();
            if (string.IsNullOrEmpty(msg))
            {
                _currentFlow.Begin();
                ispass = true;
                _selectedExamInfo.ExamState = ExamState.考试中;
                _selectedExamInfo.Permission.CanCommit = true;
                _selectedExamInfo.Permission.CanCheckState = true;
                _selectedExamInfo.Permission.CanPrint = false;
                _selectedExamInfo.Permission.CanInput = false;
                _selectedExamInfo.Permission.CanBeginExam = false;
                _selectedExamInfo.Permission.CanSelectQuestion = false;
                Send<string>("加载题目中......", MessageToken.CloseExamLoadMessage);
            }
            else
            {
                Send<string>("加载题目中......", MessageToken.CloseExamLoadMessage);
                await Task.Delay(500);
                Send<string>(msg, MessageToken.ShowExamMessage);
                _selectedExamInfo.Permission.CanBeginExam = true;
            }
            if (ispass)
            {
                ExamInfoMessage exmsg = new ExamInfoMessage()
                                          {
                                              ExamInfo = _selectedExamInfo,
                                              IsFirstShow = true,
                                              ButtonInformations = _buttonInformations,
                                              IsStep = this._isStep,
                                              Points = _points
                                          };
                //开始考试，弹出考试状态窗口
                Send<ExamInfoMessage>(exmsg, MessageToken.ShowExamingWindow);
            }
        }
        private void CheckStateExec()
        {
            var msg = new ExamInfoMessage()
                          {
                              ExamInfo = _selectedExamInfo,
                              IsFirstShow = false,
                              ButtonInformations = _buttonInformations,
                              IsStep = this._isStep,
                              Points = _points
                          };
            Send<ExamInfoMessage>(msg, MessageToken.ShowExamingWindow);
        }

        private void SelectQuestionExec()
        {
            Send<string>(_config.WorkflowClassName,MessageToken.SelectQuestion);
        }

        private void LinkExec()
        {
            if (_config != null)
            {
                if (_selectedExamInfo != null)
                {
                    bool isOpcLinked = LinkOpcServer(_config);
                    if (_config.IsInner)
                    {
                        if (isOpcLinked)
                        {
                            _isInputed = false;
                            _selectedExamInfo.ExamState = ExamState.空闲;
                            _selectedExamInfo.Permission.CanInput = true;
                            _selectedExamInfo.Permission.CanSelectQuestion = true;
                            _selectedExamInfo.Permission.CanLink = false;
                        }
                    }
                    else
                    {
                        this.IsSerialPortConnected = LinkSerialPort(_config);
                        if (IsOPCConnected && IsSerialPortConnected)
                        {
                            _selectedExamInfo.ExamState = ExamState.空闲;
                            _selectedExamInfo.Permission.CanInput = true;
                            _selectedExamInfo.Permission.CanSelectQuestion = true;
                        }
                    }
                }
                Global.CurrentWorkflowName = _config.WorkflowClassName;
                InitFlowButtonInfo(_config.WorkflowClassName);
            }
        }

        private void InitFlowButtonInfo(string className)
        {
            _buttonInformations = new List<ButtonInformation>();
            var config = Tool.GetRegulationButtons(className);
            if (config != null && config.Items.Count > 0)
            {
                foreach (var item in config.Items)
                {
                    ButtonInformation button = new ButtonInformation() { Description = item.Name };
                    _buttonInformations.Add(button);
                }
            }
        }

        private void InputExec()
        {
            Send(MessageToken.ShowInputNumber);
        }

       
        #endregion

        #region 连接设备和组态软件
        private bool LinkSerialPort(ConfigModel configModel)
        {
            var issuccess = false;
            try
            {
                if (_port != null)
                {
                    _port.Close();
                }

                _port = new SerialPort
                {
                    StopBits = configModel.StopBit,
                    DataBits = configModel.DataBit,
                    Parity = configModel.Parity,
                    BaudRate = configModel.BaudRate,
                    PortName = configModel.Name
                };
                try
                {
                    _port.Open();
                    issuccess = true;
                }
                catch (Exception ex)
                {
                    Tools.LogTool.WriteErrorLog(ex);
                }
            }
            catch (Exception ex)
            {
                Tools.LogTool.WriteErrorLog(ex);
            }

            return issuccess;
        }

        private bool LinkOpcServer(ConfigModel configModel)
        {
            bool issuccess = false;
            try
            {
                Process[] p = Process.GetProcessesByName("McgsRun");

                if (p.Count() == 1)
                {
                    _opcServer = new OPCServer();
                    _opcServer.Connect(configModel.OPCServerName, configModel.IP);
                    _opcServer.ServerShutDown += _opcserver_ServerShutDown;

                    issuccess = true;
                    this.IsOPCConnected = true;
                }
                else if (p.Count() > 1)
                {
                    ShowMessage("请打开任务管理器，结束掉所有\"McgsRun.exe\"进程，然后重新打开组态环境并运行");
                }
                else
                {
                    ShowMessage("请先打开组态软件并运行");
                }
            }
            catch (Exception ex)
            {
                Tools.LogTool.WriteErrorLog(ex);
                Console.WriteLine(ex);
                issuccess = false;
                ShowMessage("组态软件连接失败");
            }
            return issuccess;
        }

        void _opcserver_ServerShutDown(string Reason)
        {
            _selectedExamInfo.Permission.CanLink = true;
            this.IsOPCConnected = false;
        }
        #endregion
        void InitExamInfoes()
        {
            ExamInfoes = new ObservableCollection<ExamInfo>();
            ExamInfo examInfo = new ExamInfo()
            {
                Index = 1,
                ExamState = ExamState.未连接,
            };

            ExamInfoes.Add(examInfo);
            _selectedExamInfo = examInfo;
        }
    }
}
